import 'dart:ffi' as ffi;
import 'package:ffi/ffi.dart';
import 'package:tencent_rtc/bindings/ffi_bindings.dart' as native;
import 'package:tencent_rtc/bindings/load_dynamic_lib.dart';
import 'package:tencent_rtc/bindings/trtc_cloud_struct.dart';

import 'package:tencent_rtc/tx_device_manager.dart';

class TXDeviceManagerNative {
  late native.FFIBindings _deviceManagerFFIBindings;
  late tx_device_manager _deviceManagerNativePointer;

  TXDeviceManagerNative(tx_device_manager deviceManagerNativePointer) {
    _deviceManagerNativePointer = deviceManagerNativePointer;
    _deviceManagerFFIBindings = native.FFIBindings(LoadDynamicLib().loadTRTCSDK());
  }

  tx_device_manager getNativePointer() {
    return _deviceManagerNativePointer;
  }

  bool isFrontCamera() {
    try {
      return _deviceManagerFFIBindings.is_front_camera(_deviceManagerNativePointer) == 1;
    } catch (e) {
      print(e);
      return false;
    }
  }


  int setAudioRoute(int route) {
    try {
      return _deviceManagerFFIBindings.set_audio_route(_deviceManagerNativePointer, route);
    } catch (e) {
      print(e);
      return -1;
    }
  }

  int switchCamera(bool frontCamera) {
    try {
      return _deviceManagerFFIBindings.switch_camera(_deviceManagerNativePointer, frontCamera);
    } catch (e) {
      print(e);
      return -1;
    }
  }

  int enableCameraAutoFocus(bool enabled) {
    try {
      return _deviceManagerFFIBindings.enable_camera_auto_focus(_deviceManagerNativePointer, enabled);
    } catch (e) {
      print(e);
      return -1;
    }
  }

  int enableCameraTorch(bool enabled) {
    try {
      return _deviceManagerFFIBindings.enable_camera_torch(_deviceManagerNativePointer, enabled);
    } catch (e) {
      print(e);
      return -1;
    }
  }

  int enableFollowingDefaultAudioDevice(TXMediaDeviceType type, bool enable) {
    try {
      return _deviceManagerFFIBindings.enable_following_default_audio_device(_deviceManagerNativePointer, type.value(), enable);
    } catch (e) {
      print(e);
      return -1;
    }
  }

  int getApplicationMuteState() {
    try {
      return _deviceManagerFFIBindings.get_application_mute_state(_deviceManagerNativePointer);
    } catch (e) {
      print(e);
      return -1;
    }
  }

  int getApplicationPlayVolume() {
    try {
      return _deviceManagerFFIBindings.get_application_play_volume(_deviceManagerNativePointer);
    } catch (e) {
      print(e);
      return -1;
    }
  }

  double getCameraZoomMaxRatio() {
    try {
      return _deviceManagerFFIBindings.get_camera_zoom_max_ratio(_deviceManagerNativePointer);
    } catch (e) {
      print(e);
      return -1.0;
    }
  }

  TXDeviceInfo getCurrentDevice(TXMediaDeviceType type) {
    TXDeviceInfo deviceInfo = new TXDeviceInfo();

    ffi.Pointer<tx_device_info_t> deviceInfoPointer = tx_device_info_t.create();

    _deviceManagerFFIBindings.get_current_device(_deviceManagerNativePointer, type.value(), deviceInfoPointer);

    if (deviceInfoPointer != ffi.nullptr) {
      deviceInfo.devicePid = FFIConverter.getStringFromChar(deviceInfoPointer.ref.device_pid);
      deviceInfo.deviceName = FFIConverter.getStringFromChar(deviceInfoPointer.ref.device_name);
      deviceInfo.deviceProperties = FFIConverter.getStringFromChar(deviceInfoPointer.ref.device_properties);
    }

    return deviceInfo;
  }

  bool getCurrentDeviceMute(TXMediaDeviceType type) {
    int result = _deviceManagerFFIBindings.get_current_device_mute(_deviceManagerNativePointer, type.value());
    return result != 0;
  }

  int getCurrentDeviceVolume(TXMediaDeviceType type) {
    return _deviceManagerFFIBindings.get_current_device_volume(_deviceManagerNativePointer, type.value());
  }

  List<TXDeviceInfo> getDevicesList(TXMediaDeviceType type) {
    List<TXDeviceInfo> devices = <TXDeviceInfo>[];

    int count = _deviceManagerFFIBindings.get_device_count(_deviceManagerNativePointer, type.value());

    for (int index = 0; index < count; index++) {
      TXDeviceInfo deviceInfo = new TXDeviceInfo();
      ffi.Pointer<tx_device_info_t> deviceInfoPointer = tx_device_info_t.create();

      _deviceManagerFFIBindings.get_device_info(_deviceManagerNativePointer, type.value(), index, deviceInfoPointer);

      deviceInfo.devicePid = FFIConverter.getStringFromChar(deviceInfoPointer.ref.device_pid);
      deviceInfo.deviceName = FFIConverter.getStringFromChar(deviceInfoPointer.ref.device_name);
      deviceInfo.deviceProperties = FFIConverter.getStringFromChar(deviceInfoPointer.ref.device_properties);

      devices.add(deviceInfo);
    }

    return devices;
  }

  bool isAutoFocusEnabled() {
    int result = _deviceManagerFFIBindings.is_audio_focus_enabled(_deviceManagerNativePointer);
    return result != 0;
  }

  int setApplicationMuteState(bool mute) {
    return _deviceManagerFFIBindings.set_application_mute_state(_deviceManagerNativePointer, mute);
  }

  int setApplicationPlayVolume(int volume) {
    return _deviceManagerFFIBindings.set_application_play_volume(_deviceManagerNativePointer, volume);
  }

  void setCameraCaptureParam(TXCameraCaptureParam params) {
    ffi.Pointer<tx_camera_capture_param_t> paramsPointer = tx_camera_capture_param_t.fromParams(params);

    native.FFIBindings bindings = native.FFIBindings(LoadDynamicLib().loadTRTCPluginAdapter());
    // _deviceManagerFFIBindings.set_camera_capture_param(_deviceManagerNativePointer, paramsPointer.ref);
    bindings.callApi(_deviceManagerNativePointer, );

    calloc.free(paramsPointer);
  }

  int setCameraFocusPosition(double x, double y) {
    return _deviceManagerFFIBindings.set_camera_focus_position(_deviceManagerNativePointer, x, y);
  }

  int setCameraZoomRatio(double ratio) {
    return _deviceManagerFFIBindings.set_camera_zoom_ratio(_deviceManagerNativePointer, ratio);
  }

  int setCurrentDevice(TXMediaDeviceType type, String deviceId) {
    ffi.Pointer<ffi.Char> deviceIdPointer = deviceId.toNativeUtf8().cast<ffi.Char>();

    int result = _deviceManagerFFIBindings.set_current_device(_deviceManagerNativePointer, type.value(), deviceIdPointer);

    calloc.free(deviceIdPointer);
    return result;
  }

  int setCurrentDeviceMute(TXMediaDeviceType type, bool mute) {
    return _deviceManagerFFIBindings.set_current_device_mute(_deviceManagerNativePointer, type.value(), mute);
  }

  int setCurrentDeviceVolume(TXMediaDeviceType type, int volume) {
    return _deviceManagerFFIBindings.set_current_device_volume(_deviceManagerNativePointer, type.value(), volume);
  }

  int startCameraDeviceTest(int viewId) {
    tx_view txView = tx_view.fromAddress(viewId);

    return _deviceManagerFFIBindings.start_camera_device_test(_deviceManagerNativePointer, txView);
  }

  int startMicDeviceTest(int interval) {
    return _deviceManagerFFIBindings.start_mic_device_test(_deviceManagerNativePointer, interval);
  }

  int startMicDeviceTestAndPlayback(int interval, bool playback) {
    return _deviceManagerFFIBindings.start_mic_device_test_and_playback(_deviceManagerNativePointer, interval, playback);
  }

  int startSpeakerDeviceTest(String filePath) {
    ffi.Pointer<ffi.Char> filePathPointer = filePath.toNativeUtf8().cast<ffi.Char>();

    int result = _deviceManagerFFIBindings.start_speaker_device_test(_deviceManagerNativePointer, filePathPointer);

    calloc.free(filePathPointer);
    return result;
  }

  int stopCameraDeviceTest() {
    return _deviceManagerFFIBindings.stop_camera_device_test(_deviceManagerNativePointer);
  }

  int stopMicDeviceTest() {
    return _deviceManagerFFIBindings.stop_mic_device_test(_deviceManagerNativePointer);
  }

  int stopSpeakerDeviceTest() {
    return _deviceManagerFFIBindings.stop_speaker_device_test(_deviceManagerNativePointer);
  }
}
